home *** CD-ROM | disk | FTP | other *** search
- Path: Rezonet.net!news
- From: ray@ultimate-tech.com (Ray Dunn)
- Newsgroups: comp.lang.c
- Subject: Re: my atoi function, could someone suggest...
- Date: 8 Jan 1996 05:12:06 GMT
- Organization: Ultimate Technographics Inc.
- Message-ID: <4cq937$if9@ns.RezoNet.NET>
- References: <4cf7ap$q4u@kaleka.seanet.com>
- NNTP-Posting-Host: 204.19.230.7
- Mime-Version: 1.0
- Content-Type: Text/Plain; charset=US-ASCII
- X-Newsreader: WinVN 0.99.7
-
- In referenced article, where am i? says...
- >Hello. This is my first attempt at an atoi function. Although it
- >works and behaves just like atoi, I was wondering if anyone would care
- >for a look and make suggestions back to me about its efficiency.
- >
- >int atoi ( char *change )
- >{
- > int newint = 0, sign = 1;
- >
- > while ( *change )
- > {
- > if ( (*change < '0' || *change > '9') && *change != '-' )
- > {
- > *change++;
- > }
- > else
- > {
- > if ( *change == '-' )
- > {
- > *change++;
- > if ( *change >= '0' && *change <= '9' )
- > sign = -1;
- > }
- > if ( *change >= '0' && *change <= '9' )
- > {
- > while ( sign )
- > {
- > newint *= 10;
- > newint = newint + *change - 48;
- > *change++;
- > if ( *change < '0' || *change >
- '9')
- > {
- > return ( newint * sign );
- > exit (0);
- > }
- > }
- > }
- > }
- > }
- > return ( 0 );
- >}
-
- This only behaves like the "real" atoi in a limited number of cases.
-
- atoi allows the number to be preceded by any whitespace character.
-
- It returns 0 if the first character met after the whitespace is not a
- digit or a sign, or if the first character after a sign is not a digit.
-
- It also allows '+' as well as '-' for the sign
-
- In your code, all occurrences of "*change++;" should be "change++;".
-
- Your use of "48" is opaque, you should use "'0'".
-
- Your use of "exit(0);" after "return(0);" is unneccessary, and you
- don't want to exit here under any circumstances anyway, so the line
- should be removed.
-
- Your use of "while (sign)" is bizarre. "sign" is *always* non-zero,
- and thus always true, and although you may want such a loop here, it
- doesn't show your intent.
-
- Your encompasing "while (*change)" block *looks* as if its driving the
- whole scan, but in fact it only drives the initial scan for a sign or
- digit, and should only encompass that code.
-
- Your routine cannot handle the largest negative integer (-32768 if
- 16bit ints). Even though it may *appear* to work, because adding 8 to
- 32760 creates 0x8000, i.e. -32768, which remains the same if multiplied
- by -1, it actually causes integer overflow, which will cause an
- exception on some machines.
-
- Nitpicking:
-
- The name of your parameter "change" is inappropriate.
-
- You shouldn't name your function the same as one in the library.
-
- The function demonstrates clearly that 8-character indents make
- programs difficult to read (asbestos suit on).
-
- Please don't take this criticism harshly, posting code will always lead
- to nitpicking, and learning to handle all error conditions and
- pathalogical cases comes with experience. But remember - handling the
- error conditions properly is just as important as handling the "real"
- cases.
-
- Here's my attempt. Note that you need to include <ctype.h> for isspace
- and isdigit, and that the routine crashes if string is NULL (as it does
- on most systems unfortunately). You can write your own code for
- isspace and isdigit if you want this to be "all your own" code.
-
- int new_atoi (char *string)
- {
- int newint;
- int negative; /* really Boolean */
-
- /* step over whitespace */
- while (isspace(*string))
- string++;
-
- /* handle leading sign */
- negative = (*string == '-');
-
- if (negative || *string == '+')
- string++;
-
- /* step through the digits */
- newint = 0;
- while (isdigit(*string))
- {
- /* subtract '0' before adding/subtracting to ensure no
- unnecessary overflow */
- if (negative)
- newint = newint * 10 - (*string - '0');
- else
- newint = newint * 10 + (*string - '0');
-
- string++;
- }
-
- return(newint);
- }
-
- Note that if written for a library where fastest execution possible is
- important, it *might* be a good idea to avoid the unnecessary initial
- multiplication of 0 by 10 , and the negative test could be brought
- outside the loop, producing two loops, one for positive and one for
- negative numbers. The only reason negative is handled separately from
- positive is to avoid overflow on the pathalogical -32768 case.
- This would give:
-
- /* step through the digits */
- newint = 0;
- if (negative)
- {
- if (isdigit(*string))
- {
- newint = '0' - *string;
- while (isdigit(*(++string)))
- newint = newint * 10 - (*string - '0');
- }
- }
- else
- {
- if (isdigit(*string))
- {
- newint = *string - '0';
- while (isdigit(*(++string)))
- newint = newint * 10 + (*string - '0');
- }
- }
- return(newint);
-
- Note also, that if you are writing your own version of atoi, it might
- be nice to consider passing a pointer to a pointer as the argument.
- This gives you the ability to return, in the argument, the address of
- the first character past the end of the scanned integer - this often
- avoids having to do strtok's or other nasties to get past the integer
- you have just scanned. (Its also nice also to have your own variations
- of strcpy and strcat that return the address of the *end* of the
- string, which you know at that stage - it often avoids having to do
- subsequent strlen's).
- --
- Ray Dunn (opinions are my own) | Phone: (514) 938 9050
- Montreal | Phax : (514) 938 5225
- ray@ultimate-tech.com | Home : (514) 630 3749
-
-